﻿using CCWin;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace rfid
{
    public partial class MainPage : Form
    {
        FRAME rx_frame = new FRAME(1024);

        /* 构造函数 */
        public MainPage()
        {
            InitializeComponent();
            /* 禁止改变窗体大小 */
            this.MinimumSize = this.Size;
            this.MaximumSize = this.Size;
        }

        /* 搜索串口 */
        private void User_SearchSerialPort()
        {
            try
            {
                /* 扫描所有串口 */
                string[] ArryPort = SerialPort.GetPortNames();
                /* 清空项 */
                txbPortName.Items.Clear();
                /* 判断是否有串口 */
                if (ArryPort.Length <= 0)
                {
                    /* 无串口 */
                    txbInfo.AppendText("未搜索到串口\r\n");
                    txbPortName.Text = null;
                    /* 不可使用连接 */
                    btnLink.Enabled = false;
                    return;
                }
                /* 添加项 */
                for (int i = 0; i < ArryPort.Length; i++)
                {
                    txbPortName.Items.Add(ArryPort[i]);
                }
                /* 默认选择0 */
                txbPortName.SelectedIndex = 0;
                txbInfo.AppendText("搜索到串口：" + string.Join(",", ArryPort) + "\r\n");
                /* 可使用连接 */
                btnLink.Enabled = true;
            }
            catch (Exception)
            {
                MessageBox.Show("串口搜索失败\r\n");
            }
        }

        private void SerialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Thread.Sleep(100);
            rx_frame.Read(SerialPort1);
        }

        /* 加载主页面 */
        private void MainPage_Load(object sender, EventArgs e)
        {
            /* 放于中心 */
            this.Left = (Screen.PrimaryScreen.Bounds.Width - this.Width) / 2;
            this.Top = (Screen.PrimaryScreen.Bounds.Height - this.Height) / 2;
            /* 搜索串口 */
            User_SearchSerialPort();
            txbBaudRate.SelectedIndex = 0;
            lblPortStatus.Text = "设备未连接";
            lblPortStatus.ForeColor = Color.Red;

            grpControl.Enabled = false;
            grpRead.Enabled = false;
            grpWrite.Enabled = false;
        }

        /* 连接 */
        private void btnLink_Click(object sender, EventArgs e)
        {
            try
            {
                if (SerialPort1.IsOpen) /* 已打开 */
                {
                    SerialPort1.Close();
                    btnLink.Text = "连接设备";
                    btnFresh.Enabled = true;
                    txbInfo.AppendText("断开" + SerialPort1.PortName + "成功\r\n");
                    lblPortStatus.Text = "设备未连接";
                    lblPortStatus.ForeColor = Color.Red;

                    txbBaudRate.Enabled = true;
                    txbPortName.Enabled = true;
                    grpControl.Enabled = false;
                    grpRead.Enabled = false;
                    grpWrite.Enabled = false;
                }
                else
                {
                    SerialPort1.PortName = txbPortName.Text;
                    SerialPort1.BaudRate = Convert.ToInt32(txbBaudRate.Text);
                    SerialPort1.DataBits = 8;
                    SerialPort1.Parity = Parity.None;
                    SerialPort1.StopBits = StopBits.One;
                    SerialPort1.ReadTimeout = 5000;
                    SerialPort1.WriteTimeout = 5000;
                    SerialPort1.Open();
                    btnLink.Text = "断开设备";
                    btnFresh.Enabled = false;
                    txbInfo.AppendText("连接" + SerialPort1.PortName + "成功\r\n");
                    lblPortStatus.Text = "设备已连接";
                    lblPortStatus.ForeColor = Color.Green;
                    
                    txbBaudRate.Enabled = false;
                    txbPortName.Enabled = false;
                    grpControl.Enabled = true;
                    grpRead.Enabled = true;
                    grpWrite.Enabled = true;
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show("设备操作失败\r\n");
            }
        }

        /* 刷新 */
        private void btnFresh_Click(object sender, EventArgs e)
        {
            User_SearchSerialPort();
        }

        /* 检测读卡器 */
        private void btnCheckReader_Click(object sender, EventArgs e)
        {
            FRAME txframe = new FRAME(128);

            rx_frame.Clear();

            txframe.cmd = 0x00;
            txframe.length = 0;
            txframe.Write(SerialPort1);

            grpControl.Enabled = false;
            grpDevice.Enabled = false;
            grpRead.Enabled = false;
            grpWrite.Enabled = false;
            txbInfo.AppendText("检测中...\r\n");
            if (rx_frame.mr.WaitOne(3000))
            {
                if (rx_frame.buf[0] == 0x00)
                {
                    txbInfo.AppendText("检测读卡器成功，");
                    txbInfo.AppendText("软件版本：" + rx_frame.buf[1].ToString() + "." + rx_frame.buf[2].ToString() + "." + rx_frame.buf[3].ToString() + "，");
                    txbInfo.AppendText("硬件版本：" + rx_frame.buf[4].ToString() + "." + rx_frame.buf[5].ToString() + "." + rx_frame.buf[6].ToString() + "\r\n");
                }
                else
                {
                    txbInfo.AppendText("检测读卡器失败，失败码：" + rx_frame.buf[0].ToString("X2") + "\r\n");
                }
            }
            else
            {
                txbInfo.AppendText("检测超时\r\n");
            }
            rx_frame.mr.Reset();
            grpControl.Enabled = true;
            grpDevice.Enabled = true;
            grpRead.Enabled = true;
            grpWrite.Enabled = true;
        }

        /* 读卡ID */
        private void btnReadCardID_Click(object sender, EventArgs e)
        {
            FRAME txframe = new FRAME(128);

            rx_frame.Clear();

            txframe.cmd = 0x01;
            txframe.length = 0;
            txframe.Write(SerialPort1);

            grpControl.Enabled = false;
            grpDevice.Enabled = false;
            grpRead.Enabled = false;
            grpWrite.Enabled = false;
            txbInfo.AppendText("读卡ID和类型中...\r\n");
            if (rx_frame.mr.WaitOne(3000))
            {
                if (rx_frame.buf[0] == 0x00)
                {
                    txbInfo.AppendText("读卡ID和类型成功，");
                    txbInfo.AppendText("ID：" + rx_frame.buf[1].ToString("X2") + " " + rx_frame.buf[2].ToString("X2") + " " + rx_frame.buf[3].ToString("X2") + " " + rx_frame.buf[4].ToString("X2") + "，");
                    txbInfo.AppendText("类型：" + rx_frame.buf[5].ToString("X2") + " " + rx_frame.buf[6].ToString("X2") + "\r\n");
                }
                else
                {
                    txbInfo.AppendText("读卡ID和类型失败，失败码：" + rx_frame.buf[0].ToString("X2") + "\r\n");
                }
            }
            else
            {
                txbInfo.AppendText("读卡超时\r\n");
            }
            rx_frame.mr.Reset();
            grpControl.Enabled = true;
            grpDevice.Enabled = true;
            grpRead.Enabled = true;
            grpWrite.Enabled = true;
        }

        /* 定位到最后一行 */
        private void txbInfo_TextChanged(object sender, EventArgs e)
        {
            txbInfo.ScrollToCaret();
        }

        /* 清除 */
        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            txbInfo.Clear();
        }
    }

    public class FRAME
    {
        public byte cmd;
        public byte length;
        public byte[] buf;
        private byte checksum;
        private byte count;
        private byte rx_status;

        /* 事件通知 */
        public ManualResetEvent mr;

        public FRAME(int size)
        {
            this.buf = new byte[size];
            this.cmd = 0;
            this.length = 0;
            this.checksum = 0;
            this.count = 0;
            this.rx_status = 0;
            this.mr = new ManualResetEvent(false);
        }

        public void Write(SerialPort sp)
        {
            int i;
            byte[] tx_buf = new byte[256];
            this.checksum = 0;
            tx_buf[0] = 0x00;
            tx_buf[1] = 0x00;
            tx_buf[2] = 0x55;
            tx_buf[3] = 0xAA;
            tx_buf[4] = this.cmd;
            this.checksum += this.cmd;
            tx_buf[5] = this.length;
            this.checksum += this.length;
            for (i = 0; i < this.length; i++)
            {
                tx_buf[6 + i] = this.buf[i];
                this.checksum += this.buf[i];
            }
            tx_buf[6 + i] = this.checksum;
            sp.Write(tx_buf, 0, 7 + i);
        }

        public void Read(SerialPort sp)
        {
            int len = sp.BytesToRead;
            for (int i = 0; i < len; i++)
            {
                if (this.GetByte(Convert.ToByte(sp.ReadByte())))
                {
                    this.mr.Set();
                }
            }
        }

        public void Clear()
        {
            this.rx_status = 0;
        }

        private bool GetByte(byte data)
        {
            bool res = false;

            switch (this.rx_status)
            {
                case 0:    /* 接收第一个包头 */
                    if (0x55 == data)
                    {
                        /* 接收到第一个头 */
                        this.rx_status = 1;
                    }
                    break;

                case 1:    /* 接收第二个包头 */
                    if (0xAA == data)
                    {
                        /* 接收到第二个头 */
                        this.rx_status = 2;
                        /* 清除校验和初值 */
                         this.checksum= 0;
                    }
                    else
                    {
                        /* 未收到第二个头，回到初始位置，继续接收第一个头 */
                         this.rx_status = 0;
                    }
                    break;

                case 2:
                    /* 保存命令 */
                    this.cmd = data;
                    /* 累加校验和 */
                     this.checksum+= data;
                    /* 接收数据长度 */
                     this.rx_status = 3;
                    break;

                case 3:
                    /* 保存数据长度 */
                    this.length = data;
                    /* 累加校验和 */
                     this.checksum += data;
                    /* 判断是否有数据域 */
                    if (data > 0)
                    {
                        /* 清除计算值，准备接收数据 */
                        this.count = 0;
                        /* 接收数据 */
                         this.rx_status = 4;
                    }
                    else
                    {
                        /* 接收校验 */
                         this.rx_status = 5;
                    }
                    break;

                case 4:
                    /* 保存数据 */
                    this.buf[this.count++] = data;
                    /* 累加校验和 */
                     this.checksum += data;
                    /* 判断是否接收数据完成 */
                    if (this.count >= this.length)
                    {
                        /* 接收校验 */
                         this.rx_status = 5;
                    }
                    break;

                case 5:
                    /* 判断校验结果是否一样 */
                    if (data == this.checksum)
                    {
                        /* 接收包成功 */
                        res = true;
                        /* 回到起始状态，接收下一包头 */
                         this.rx_status = 0;
                    }
                    break;

                default:
                    /* 异常状态，回到初始位置，继续接收第一个头 */
                     this.rx_status = 0;
                    break;
            }

            return res;
        }
    };
}
